import numpy as np
import pandas as pd
import qiniu
import os
import requests
from .APIKeyController import qiniuAPI
import matplotlib.pyplot as plt
from qiniu import Auth, put_file, etag
from io import BytesIO
from qiniu import CdnManager
from openpyxl import load_workbook  # 引入用于读取Excel文件的库
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score


# 获取数据集
# def getDataTrain(key):
#     access_key, secret_key, bucket_name = qiniuAPI()
#     q = Auth(access_key, secret_key)
#     private_url = q.private_download_url(key, expires=86400)
#     try:
#
#         # 发起HTTP GET请求下载文件，并保存到本地
#         data_user_dir = os.path.abspath(os.path.join("../modelLinter/static", "../static/LinearFile"))
#         if not os.path.exists(data_user_dir):
#             os.makedirs(data_user_dir)
#         local_file_path = os.path.join(data_user_dir, os.path.basename(key))  # 构造本地文件路径
#         print(local_file_path)
#         with requests.get(private_url, stream=True, timeout=30) as r:  # 使用stream=True以流方式下载
#             r.raise_for_status()  # 检查状态码是否为200，如果不是则抛出异常
#             with open(local_file_path, 'wb') as f:
#                 for chunk in r.iter_content(chunk_size=1024):
#                     if chunk:
#                         f.write(chunk)
#
#     except requests.exceptions.RequestException as req_error:
#         print(f"Network error occurred while downloading file: {req_error}")
#         return None
#
#     except Exception as e:
#         print(f"Unexpected error occurred: {e}")
#         return None
#
#     except Exception as e:
#         print(f"Unexpected error occurred: {e}")
#         return None
#
#
# def getDataTest(key):
#     access_key, secret_key, bucket_name = qiniuAPI()
#     q = Auth(access_key, secret_key)
#     bucket_domain = 'qiniuyun.linter.top'
#     try:
#         # 设置token过期时间，生成私有下载URL
#         private_url = q.private_download_url(key, expires=86400)
#
#         # 发起HTTP GET请求下载文件，并保存到本地
#         data_user_dir = os.path.abspath(os.path.join("../modelLinter/static", "../static/LinearFile"))
#         if not os.path.exists(data_user_dir):
#             os.makedirs(data_user_dir)
#         local_file_path = os.path.join(data_user_dir, os.path.basename(key))  # 构造本地文件路径
#         print(local_file_path)
#         with requests.get(private_url, stream=True, timeout=30) as r:  # 使用stream=True以流方式下载
#             r.raise_for_status()  # 检查状态码是否为200，如果不是则抛出异常
#             with open(local_file_path, 'wb') as f:
#                 for chunk in r.iter_content(chunk_size=1024):
#                     if chunk:
#                         f.write(chunk)
#
#     except requests.exceptions.RequestException as req_error:
#         print(f"Network error occurred while downloading file: {req_error}")
#         return None
#
#     except Exception as e:
#         print(f"Unexpected error occurred: {e}")
#         return None
#
#     except Exception as e:
#         print(f"Unexpected error occurred: {e}")
#         return None
#
#
# def readDataTrain(key):
#     startPath = '../modelLinter/static/LinearFile'
#     filrName = '01_data.xlsx'
#     filePath = os.path.join(startPath, filrName)
#     if os.path.exists(filePath):
#         rd = pd.read_excel("../modelLinter/static/LinearFile/01_data.xlsx", engine="openpyxl")
#         rd = pd.DataFrame(rd)
#         print(rd.head())
#         return rd
#     else:
#         getDataTrain(key)
#         rd = pd.read_excel("../modelLinter/static/LinearFile/01_data.xlsx", engine="openpyxl")
#         rd = pd.DataFrame(rd)
#         print(rd.head())
#         return rd
#
#
#
# def readDataTest(key):
#     startPath = '../modelLinter/static/LinearFile'
#     filrName = '02_data.xlsx'
#     filePath = os.path.join(startPath, filrName)
#     if os.path.exists(filePath):
#         rd = pd.read_excel("../modelLinter/static/LinearFile/02_data.xlsx", engine="openpyxl")
#         rd = pd.DataFrame(rd)
#         print(rd.head())
#         return rd
#     else:
#         getDataTrain(key)
#         rd = pd.read_excel("../modelLinter/static/LinearFile/02_data.xlsx", engine="openpyxl")
#         rd = pd.DataFrame(rd)
#         print(rd.head())
#         return rd
#

# 线性回归
class LinearRegressionPredictor:
    def __init__(self):
        """
        初始化类，传入特征列名列表和目标列名
        :param featureColumns: 特征列名列表
        :param featureColumn: 目标列名
        """
        self.featureColumns = None
        self.featureColumn = None
        self.model = None

    def fit(self, data, test_size_user, random_state_user, featureColumns, featureColumn):
        """
        训练方法，接收一个包含特征和标签的DataFrame作为参数
        :param featureColumn: 目标列名
        :param featureColumns: 特征列名列表
        :param random_state_user: 用户输入参数选择随机程度
        :param test_size_user: 用户输入参数选择测试集大小
        :param data: 用户上传的已经通过预处理的数据集
        """
        features = data[featureColumns]
        # print(features.head())
        target = data[featureColumn]
        # print(target.head())

        X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=test_size_user,
                                                            random_state=random_state_user)

        self.model = LinearRegression()
        self.model.fit(X_train, y_train)

    def predict(self, data, featureColumns):
        """
        预测方法，接收一个包含特征的DataFrame进行预测
        :param featureColumns: 特征列名列表
        :param data: 用户上传的已经通过预处理的数据集
        :return: 使用训练好的模型对输入数据进行预测
        """
        if not self.model:
            raise ValueError("Model has not been trained yet. Please call 'fit' method first.")

        self.featureColumns = featureColumns
        predictions = self.model.predict(data[self.featureColumns])
        return predictions

    def evaluate(self, data, featureColumn, featureColumns):
        """
        评估方法，计算模型在给定数据上的MSE和R²指标
        :return: MSE和R²指标
        """
        if not self.model:
            raise ValueError("Model has not been trained yet. Please call 'fit' method first.")

        self.featureColumn = featureColumn
        self.featureColumns = featureColumns
        y_true = data[self.featureColumn]
        y_pred = self.predict(data, self.featureColumns)

        mse = mean_squared_error(y_true, y_pred)
        r2 = r2_score(y_true, y_pred)
        metrics = {
            'MSE': mse,
            'R2': r2
        }

        return metrics
